package com.flow.framework.common.util.verify;

import com.flow.framework.common.error.SystemErrorCode;
import com.flow.framework.common.exception.CheckedException;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Nonnull;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import java.util.function.Supplier;

/**
 * 校验是否为空工具类
 *
 * @author luoguopiao
 * @version 0.0.1
 * @date 2022/1/3
 */
@Slf4j
public final class VerifyUtil {

    private VerifyUtil() {
    }

    /**
     * 判断两个对象是否相对
     *
     * @param o o
     * @param other other
     * @return
     */
    public static boolean objectEquals(Object o, Object other){
        return o == other || (null != o && o.equals(other)) || (null != other && other.equals(o));
    }

    /**
     * 确保对象不为null
     *
     * @param object object
     * @param <T>    object
     */
    @Nonnull
    public static <T> T requireNotNull(T object) {
        return requireNotNull(object, () -> new CheckedException(SystemErrorCode.OBJECT_NOT_FOUND_ERROR));
    }


    /**
     * 确保对象不为null
     *
     * @param object        object
     * @param errorCallback 出错回调
     * @param <T>           object
     */
    @Nonnull
    public static <T> T requireNotNull(T object, Supplier<CheckedException> errorCallback) {
        if (null == object) {
            log.error("object is null.");
            throw errorCallback.get();
        }
        return object;
    }

    /**
     * 确保对象不为空
     *
     * @param object object
     * @param <T>    object
     */
    @Nonnull
    public static <T> T requireNotEmpty(T object) {
        return requireNotEmpty(object, () -> new CheckedException(SystemErrorCode.OBJECT_NOT_FOUND_ERROR));
    }


    /**
     * 确保对象不为空
     *
     * @param object        object
     * @param errorCallback 出错回调
     * @param <T>           object
     */
    @Nonnull
    public static <T> T requireNotEmpty(T object, Supplier<CheckedException> errorCallback) {
        if (VerifyUtil.isEmpty(object)) {
            log.error("object is empty.");
            throw errorCallback.get();
        }
        return object;
    }

    /**
     * 确保对象没有空值
     *
     * @param objects objects
     */
    public static void requireNotHasEmpty(Object... objects) {
        requireNotHasEmpty(() -> new CheckedException(SystemErrorCode.OBJECT_NOT_FOUND_ERROR), objects);
    }

    /**
     * 确保对象没有空值
     *
     * @param errorCallback 出错回调
     * @param objects       objects
     */
    public static void requireNotHasEmpty(Supplier<CheckedException> errorCallback, Object... objects) {
        if (null == objects || objects.length == 0) {
            log.error("objects has empty.");
            throw new CheckedException(SystemErrorCode.PARAMS_ERROR);
        }
        for (Object object : objects) {
            if (isEmpty(object)) {
                log.error("objects element has empty.");
                throw new CheckedException(SystemErrorCode.PARAMS_ERROR);
            }
        }
    }

    /**
     * 判断Boolean是否为true
     *
     * @param tag tag
     * @return
     */
    public static boolean isTrue(Boolean tag) {
        return !isEmpty(tag) && tag;
    }

    /**
     * 判断对象是否为空，如果变量声明的类型为Object或无法找到匹配类型，则会调调用方法
     *
     * @param o object
     * @return
     */
    public static boolean isEmpty(Object o) {
        if (null == o) {
            return true;
        } else if (o instanceof CharSequence) {
            CharSequence temp = (CharSequence) o;
            return isEmpty(temp);
        } else if (o instanceof Collection) {
            Collection temp = (Collection) o;
            return isEmpty(temp);
        } else if (o instanceof Map) {
            Map temp = (Map) o;
            return isEmpty(temp);
        } else if (o.getClass().isArray()) {
            return 0 == Array.getLength(o);
        } else {
            return false;
        }
    }

    /**
     * 判断对象是否为空，如果变量声明的类型为String，则会调用该方法
     *
     * @param s 字符串
     * @return
     */
    public static boolean isEmpty(CharSequence s) {
        if (s instanceof String) {
            String temp = (String) s;
            return temp.trim().isEmpty();
        }
        return s == null || s.length() == 0;
    }

    /**
     * 判断对象是否为空，如果变量声明的类型为Collection，则会调用该方法
     *
     * @param collection 容器
     * @return
     */
    public static boolean isEmpty(Collection collection) {
        return collection == null || collection.isEmpty();
    }

    /**
     * 判断对象是否为空，如果变量声明的类型为Map，则会调用该方法
     *
     * @param map map
     * @return
     */
    public static boolean isEmpty(Map map) {
        return map == null || map.isEmpty();
    }

    /**
     * 判断数组中的对象是否存在空的情况
     *
     * @param objects objects
     * @return
     */
    public static boolean hasEmpty(Object... objects) {
        if (null == objects || objects.length == 0) {
            return true;
        }
        for (Object object : objects) {
            if (isEmpty(object)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断数组中的对象是否存在不空的情况
     *
     * @param objects objects
     * @return
     */
    public static boolean hasNotEmpty(Object... objects) {
        if (null == objects || objects.length == 0) {
            return false;
        }
        for (Object object : objects) {
            if (!isEmpty(object)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断数组是否为空
     *
     * @param objs objs
     * @return
     */
    public static boolean isEmpty(Object[] objs) {
        return objs == null || objs.length == 0;
    }
}
